package com.example.demo.services;


import com.example.demo.config.websocket.StockInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class StockInfoService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    //    缓存消息（主要用来处理用户不在线时收到的消息）
    public void stockInfoToRedis(String senderId, String receiverId, String message, String userNickName, String userNickAvatar) throws JsonProcessingException {
//        创建缓存信息
        StockInfo stockInfo = StockInfo.builder()
                .from(senderId)
                .to(receiverId)
                .timeStamp(Instant.now())
                .userNickName(userNickName)
                .userNickAvatar(userNickAvatar).build();
//        将Map转换为JSON字符串
        String messageJSON = objectMapper.writeValueAsString(stockInfo);
//        构造redis键
        String redisKey = "stockInfo:" + receiverId + "-" + senderId;
//        将消息存储到redis中
        stringRedisTemplate.opsForList().rightPush(redisKey, messageJSON);
//        设置redis键的过期时间（可选（选择了=时间到了你连看到的机会都没有））
        stringRedisTemplate.expire(redisKey, 24, TimeUnit.HOURS);
    }

    //    缓存离线群聊信息
    public void stockOffOnlineMessage(String memberId, String message, String senderId, String userNickName, String userNickAvatar, String groupId) throws JsonProcessingException {
//        构造群聊信息key
        String cacheKey = "offlineGroupMessages" + ":" + groupId + "-:" + memberId;
        // 构造离线群聊缓存信息
        StockInfo stockInfo = StockInfo.builder()
                .from(senderId).timeStamp(Instant.now()).message(message)
                .userNickName(userNickName).userNickAvatar(userNickAvatar).groupId(groupId).build();
        String messageJSON = objectMapper.writeValueAsString(stockInfo);
        stringRedisTemplate.opsForList().rightPush(cacheKey, messageJSON);
    }


    public void StockCommonTextInfo(String senderId, String receiverId, String memberId, String message, String userNickName, String userNickAvatar, String groupId, List<String> atList) throws JsonProcessingException {

//        构造对象
        StockInfo stockInfo = StockInfo.builder().id(UUID.randomUUID().toString().substring(0, 10))
                .from(senderId).to(receiverId).message(message)
                .userNickName(userNickName).userNickAvatar(userNickAvatar).timeStamp(Instant.now()).groupId(groupId).atList(atList)
                .Type("TEXT").build();

//        将对象转换为JSON字符串
        String messageJSON = objectMapper.writeValueAsString(stockInfo);

//        根据私聊和群聊生成对应的Redis key
        String stockKey = groupId != null ? "offlineGroupMessages" + ":" + groupId + "-:" + memberId : "stockInfo:" + receiverId + "-" + senderId;

//        获取list列表
        ListOperations<String, String> listOps = redisTemplate.opsForList();
        listOps.rightPush(stockKey, messageJSON);       // rightPush会自动判断redis key是否存在
//        if (redisTemplate.hasKey(stockKey)) {
//            listOps.rightPush(stockKey, messageJSON);
//        } else {
//            listOps.leftPush(stockKey, messageJSON);
//        }
    }


    //    通过消息Key获取整个lists（只用来获取私聊缓存信息）
    public List<Map<String, Object>> getOffLineMessageInfo(String key) throws JsonProcessingException {
//        在redis中获取消息列表
        List<String> messageList = stringRedisTemplate.opsForList().range(key, 0, -1);
//        如果离线消息列表为空，直接返回空列表
        if (messageList == null || messageList.isEmpty()) {
            return new ArrayList<>();
        }

//        创建一个列表来存储反序列化后的对象
        List<Map<String, Object>> messages = new ArrayList<>();

//        遍历消息列表并反序列化每个JSON对象
        for (String messageJSON : messageList) {
//            TypeReference是一个抽象类，用于在反序列化时提供具体的泛型类型信息（解决java的类型擦除机制(泛型信息在运行时会被擦除)）
            Map<String, Object> message = objectMapper.readValue(messageJSON, new TypeReference<Map<String, Object>>() {
            });
            messages.add(message);
        }
        return messages;
    }

    public List<Map<String, Object>> getOffLineGroupMessageInfo(String key, String groupId) throws JsonProcessingException {
        List<String> groupMessageList = stringRedisTemplate.opsForList().range(key, 0, -1);
        if (groupMessageList == null || groupMessageList.isEmpty()) {
            return new ArrayList<>();
        }
//        创建一个列表存储反序列化之后的对象
        List<Map<String, Object>> groupMessages = new ArrayList<>();
        for (String groupMessageJSON : groupMessageList) {
            Map<String, Object> groupMessage = objectMapper.readValue(groupMessageJSON, new TypeReference<Map<String, Object>>() {
            });
            groupMessages.add(groupMessage);
        }
        return groupMessages;
    }


    //    缓存群聊、私聊文件离线信息
    public void stockFileMessage(Map<String, Object> payload, Optional<List<String>> memberKeys) throws JsonProcessingException {
        String mimeType = payload.get("mimeType").toString();
        String senderId = payload.get("senderId").toString();
        String toChatId = payload.get("to").toString();
        String redisKey = "";
        List<String> atList = getAtList(payload);
        //        构建文件消息
        Map<String, Object> fileMap = new HashMap<>();
        fileMap.put("fileName", payload.get("fileName").toString());
        fileMap.put("fileSize", payload.get("fileSize").toString());
        fileMap.put("fileKey", payload.get("fileKey").toString());
        if (mimeType != null && mimeType.startsWith("image/")) {
            fileMap.put("fileUrl", payload.get("fileUrl").toString());
        }
//        构造统一的文件对象
        StockInfo stockInfo = StockInfo.builder().id(UUID.randomUUID().toString().substring(0, 10))
                .from(senderId)
                .to(toChatId)
                .timeStamp(Instant.now())
                .userNickName(payload.get("userNickName").toString())
                .userNickAvatar(payload.get("userNickAvatar").toString()).groupId(toChatId)
                .message(objectMapper.writeValueAsString(fileMap)).atList(atList).Type("FILE").build();

//        将对象序列化为字符串
        String messageStockJson = objectMapper.writeValueAsString(stockInfo);

        //        获取List操作对象
        ListOperations<String, String> listOps = redisTemplate.opsForList();

//        根据memberKeys来生成对应的redis key（要生成私聊缓存文件的key和群聊缓存文件的key）
        if (memberKeys.isEmpty()) {
            redisKey = "stockInfo:" + toChatId + "-" + senderId;
            listOps.rightPush(redisKey, messageStockJson);
//            设置过期时间
            setKeyExpiration(redisKey, Duration.ofDays(7));
        } else {
//            在Optional中提取List
//            List<String> keys = memberKeys.get();   // 确保 memberKeys 不为空，因此可以安全调用 get()
            for (String messageKey : memberKeys.orElse(new ArrayList<>())) {
                redisKey = "offlineGroupMessages:" + toChatId + "-:" + messageKey;
//                然后进行存储操作
                listOps.rightPush(redisKey, messageStockJson);
                setKeyExpiration(redisKey, Duration.ofDays(7));
            }
        }

//        根据私聊信息和群聊信息生成对应的key来缓存
//        String key = atList.map(s -> "offlineGroupMessages:" + s + "-:" + userId).orElseGet(() -> "stockInfo:" + userId + "-" + senderId);
//        检查是否存在相同的key，存在则直接添加，反之创建添加
//        listOps.rightPush(key, messageStockJson);

    }

    //    获取atList列表
    private List<String> getAtList(Map<String, Object> payload) {
        return Optional.ofNullable(payload.get("atList"))
                .filter(List.class::isInstance)
                .map(object -> ((List<?>) object).stream()
                        .map(String::valueOf)
                        .filter(s -> !s.isBlank())
                        .toList())
                .filter(list -> !list.isEmpty())
                .orElse(null);
    }

    //    给redis缓存信息的key过期时间
    private void setKeyExpiration(String key, Duration duration) {
        redisTemplate.expire(key, duration);
    }

}
